home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / MBUF.C < prev    next >
C/C++ Source or Header  |  1990-03-15  |  11KB  |  550 lines

  1. /* Primitive mbuf allocate/free routines */
  2.  
  3. #include "global.h"
  4. #include "mbuf.h"
  5.  
  6. /* Allocate mbuf with associated buffer of 'size' bytes */
  7. struct mbuf *
  8. alloc_mbuf(size)
  9. int16 size;
  10. {
  11.     register struct mbuf *bp;
  12.  
  13.     if((bp = (struct mbuf *)malloc((unsigned)(size + sizeof(struct mbuf)))) == NULLBUF)
  14.         return NULLBUF;
  15.     bp->next = bp->anext = NULLBUF;
  16.     if(size != 0){
  17.         bp->data = (char *)(bp + 1);
  18.     } else {
  19.         bp->data = NULLCHAR;
  20.     }
  21.     bp->size = size;
  22.     bp->cnt = 0;
  23.     return bp;
  24. }
  25.  
  26. /* Free all resources associated with mbuf
  27.  * Return pointer to next mbuf in packet chain
  28.  */
  29. struct mbuf *
  30. free_mbuf(bp)
  31. register struct mbuf *bp;
  32. {
  33.     register struct mbuf *bp1 = NULLBUF;
  34.  
  35.     if(bp != NULLBUF){
  36.         bp1 = bp->next;
  37.         bp->next = NULLBUF;    /* detect attempts to use */
  38.         bp->data = NULLCHAR;    /* a freed mbuf */
  39.         free((char *)bp);
  40.     }
  41.     return bp1;
  42. }
  43.  
  44. /* Free packet (a chain of mbufs). Return pointer to next packet on queue,
  45.  * if any
  46.  */
  47. struct mbuf *
  48. free_p(bp)
  49. register struct mbuf *bp;
  50. {
  51.     struct mbuf *abp;
  52.  
  53.     if(bp == NULLBUF)
  54.         return NULLBUF;
  55.     abp = bp->anext;
  56.     while(bp != NULLBUF)
  57.         bp = free_mbuf(bp);
  58.     return abp;
  59. }
  60. /* Free entire queue of packets (of mbufs) */
  61. free_q(q)
  62. struct mbuf **q;
  63. {
  64.     register struct mbuf *bp;
  65.  
  66.     while((bp = dequeue(q)) != NULLBUF)
  67.         free_p(bp);
  68. }
  69.  
  70. /* Count up the total number of bytes in an mbuf */
  71. int16
  72. len_mbuf(bp)
  73. register struct mbuf *bp;
  74. {
  75.     register int cnt;
  76.  
  77.     cnt = 0;
  78.     while(bp != NULLBUF){
  79.         cnt += bp->cnt;
  80.         bp = bp->next;
  81.     }
  82.     return cnt;
  83. }
  84. /* Count up the number of packets in a queue */
  85. int16
  86. len_q(bp)
  87. register struct mbuf *bp;
  88. {
  89.     register int cnt;
  90.  
  91.     for(cnt=0;bp != NULLBUF;cnt++,bp = bp->anext)
  92.         ;
  93.     return cnt;
  94. }
  95. /* Trim mbuf to specified length by lopping off end */
  96. trim_mbuf(bpp,length)
  97. struct mbuf **bpp;
  98. int16 length;
  99. {
  100.     register int16 tot = 0;
  101.     register struct mbuf *bp;
  102.  
  103.     if(bpp == NULLBUFP || *bpp == NULLBUF)
  104.         return; /* Nothing to trim */
  105.  
  106.     if(length == 0){
  107.         /* Toss the whole thing */
  108.         free_p(*bpp);
  109.         *bpp = NULLBUF;
  110.         return;
  111.     }
  112.     /* Find the point at which to trim. If length is greater than
  113.      * the packet, we'll just fall through without doing anything
  114.      */
  115.     for( bp = *bpp; bp != NULLBUF; bp = bp->next){
  116.         if(tot + bp->cnt < length){
  117.             tot += bp->cnt;
  118.         } else {
  119.             /* Cut here */
  120.             bp->cnt = length - tot;
  121.             free_p(bp->next);
  122.             bp->next = NULLBUF;
  123.             break;
  124.         }
  125.     }
  126. }
  127. /* Duplicate/enqueue/dequeue operations based on mbufs */
  128.  
  129. /* Duplicate first 'cnt' bytes of packet starting at 'offset'.
  130.  * This is done without copying data; only the headers are duplicated,
  131.  * but without data segments of their own. The pointers are set up to
  132.  * share the data segments of the original copy. The return pointer is
  133.  * passed back through the first argument, and the return value is the
  134.  * number of bytes actually duplicated.
  135.  */
  136. int16
  137. dup_p(hp,bp,offset,cnt)
  138. struct mbuf **hp;
  139. register struct mbuf *bp;
  140. register int16 offset;
  141. register int16 cnt;
  142. {
  143.     register struct mbuf *cp;
  144.     int16 tot;
  145.  
  146.     if(cnt == 0 || bp == NULLBUF || hp == NULLBUFP){
  147.         if(hp != NULLBUFP)
  148.             *hp = NULLBUF;
  149.         return 0;
  150.     }
  151.     if((*hp = cp = alloc_mbuf(0)) == NULLBUF){
  152.         return 0;
  153.     }
  154.     /* Skip over leading mbufs that are smaller than the offset */
  155.     while(bp != NULLBUF && bp->cnt <= offset){
  156.         offset -= bp->cnt;
  157.         bp = bp->next;
  158.     }
  159.     if(bp == NULLBUF){
  160.         free_mbuf(cp);
  161.         *hp = NULLBUF;
  162.         return 0;    /* Offset was too big */
  163.     }
  164.     tot = 0;
  165.     for(;;){
  166.         cp->data = bp->data + offset;
  167.         cp->cnt = min(cnt,bp->cnt - offset);
  168.         offset = 0;
  169.         cnt -= cp->cnt;
  170.         tot += cp->cnt;
  171.         bp = bp->next;
  172.         if(cnt == 0 || bp == NULLBUF || (cp->next = alloc_mbuf(0)) == NULLBUF)
  173.             break;
  174.         cp = cp->next;
  175.     }
  176.     return tot;
  177. }
  178. /* Copy first 'cnt' bytes of packet into a new, single mbuf */
  179. struct mbuf *
  180. copy_p(bp,cnt)
  181. register struct mbuf *bp;
  182. register int16 cnt;
  183. {
  184.     register struct mbuf *cp;
  185.     register char *wp;
  186.     register int16 n;
  187.  
  188.     if(bp == NULLBUF || cnt == 0 || (cp = alloc_mbuf(cnt)) == NULLBUF)
  189.         return NULLBUF;
  190.     wp = cp->data;
  191.     while(cnt != 0 && bp != NULLBUF){
  192.         n = min(cnt,bp->cnt);
  193.         memcpy(wp,bp->data,n);
  194.         wp += n;
  195.         cp->cnt += n;
  196.         cnt -= n;
  197.         bp = bp->next;
  198.     }
  199.     return cp;
  200. }
  201. /* Copy and delete "cnt" bytes from beginning of packet. Return number of
  202.  * bytes actually pulled off
  203.  */
  204. int16
  205. pullup(bph,buf,cnt)
  206. register struct mbuf **bph;
  207. register char *buf;
  208. register int16 cnt;
  209. {
  210.     register struct mbuf *bp;
  211.     int16 tot;
  212.  
  213.     if(bph == NULLBUFP)
  214.         return 0;
  215.     tot = 0;
  216.     while(cnt != 0 && *bph != NULLBUF){
  217.         if((bp = *bph)->cnt != 0){
  218.         if(cnt < bp->cnt){
  219.             if(cnt == 1){
  220.             if(buf != NULLCHAR)
  221.                 *buf = *bp->data;
  222.             bp->data++;
  223.             bp->cnt--;
  224.             } else {
  225.             if(buf != NULLCHAR)
  226.                 memcpy(buf,bp->data,cnt);
  227.             bp->data += cnt;
  228.             bp->cnt -= cnt;
  229.             }
  230.  
  231.             return (tot + cnt);
  232.         }
  233.  
  234.         if(bp->cnt == 1){
  235.             if(buf != NULLCHAR)
  236.             *buf++ = *bp->data;
  237.             tot++;
  238.             cnt--;
  239.         } else {
  240.             if(buf != NULLCHAR){
  241.             memcpy(buf,bp->data,bp->cnt);
  242.             buf += bp->cnt;
  243.             }
  244.             tot += bp->cnt;
  245.             cnt -= bp->cnt;
  246.         }
  247.         }
  248.  
  249.         *bph = free_mbuf(bp);
  250.     }
  251.     return tot;
  252. }
  253. /* Append mbuf to end of mbuf chain */
  254. void
  255. append(bph,bp)
  256. struct mbuf **bph;
  257. struct mbuf *bp;
  258. {
  259.     register struct mbuf *p;
  260.  
  261.     if(bph == NULLBUFP || bp == NULLBUF)
  262.         return;
  263.     if(*bph == NULLBUF){
  264.         /* First one on chain */
  265.         *bph = bp;
  266.     } else {
  267.         for(p = *bph ; p->next != NULLBUF ; p = p->next)
  268.             ;
  269.         p->next = bp;
  270.     }
  271. }
  272. /* Insert specified amount of contiguous new space at the beginning of an
  273.  * mbuf chain. If enough space is available in the first mbuf, no new space
  274.  * is allocated. Otherwise a mbuf of the appropriate size is allocated and
  275.  * tacked on the front of the chain.
  276.  *
  277.  * This operation is the logical inverse of pullup(), hence the name.
  278.  */
  279. struct mbuf *
  280. pushdown(bp,size)
  281. register struct mbuf *bp;
  282. int16 size;
  283. {
  284.     register struct mbuf *nbp;
  285.  
  286.     /* Check that bp is real and that there's data space associated with
  287.      * this buffer (i.e., this is not a buffer from dup_p) before
  288.      * checking to see if there's enough space at its front
  289.      */
  290.     if(bp != NULLBUF && bp->size != 0 && bp->data - (char *)(bp+1) >= size){
  291.         /* No need to alloc new mbuf, just adjust this one */
  292.         bp->data -= size;
  293.         bp->cnt += size;
  294.     } else {
  295.         if((nbp = alloc_mbuf(size)) != NULLBUF){
  296.             nbp->next = bp;
  297.             nbp->cnt = size;
  298.             bp = nbp;
  299.         } else {
  300.             bp = NULLBUF;
  301.         }
  302.     }
  303.     return bp;
  304. }
  305. /* Append packet to end of packet queue */
  306. void
  307. enqueue(q,bp)
  308. struct mbuf **q;
  309. struct mbuf *bp;
  310. {
  311.     register struct mbuf *p;
  312.     int i_state;
  313.  
  314.     if(q == NULLBUFP || bp == NULLBUF)
  315.         return;
  316.     i_state = disable();
  317.     if(*q == NULLBUF){
  318.         /* List is empty, stick at front */
  319.         *q = bp;
  320.     } else {
  321.         for(p = *q ; p->anext != NULLBUF ; p = p->anext)
  322.             ;
  323.         p->anext = bp;
  324.     }
  325.     restore(i_state);
  326. }
  327. /* Unlink a packet from the head of the queue */
  328. struct mbuf *
  329. dequeue(q)
  330. register struct mbuf **q;
  331. {
  332.     register struct mbuf *bp;
  333.     int i_state;
  334.  
  335.     if(q == NULLBUFP || *q == NULLBUF)
  336.         return NULLBUF;
  337.     i_state = disable();
  338.     bp = *q;
  339.     *q = bp->anext;
  340.     bp->anext = NULLBUF;
  341.     restore(i_state);
  342.     return bp;
  343. }
  344.  
  345. /* Copy user data into an mbuf */
  346. struct mbuf *
  347. qdata(data,cnt)
  348. char *data;
  349. int16 cnt;
  350. {
  351.     register struct mbuf *bp;
  352.  
  353.     if((bp = alloc_mbuf(cnt)) == NULLBUF)
  354.         return NULLBUF;
  355.     memcpy(bp->data,data,cnt);
  356.     bp->cnt = cnt;
  357.     return bp;
  358. }
  359. /* Copy user string into an mbuf */
  360. struct mbuf *
  361. qstring(data)
  362. char *data;
  363. {
  364.     return qdata(data,strlen(data));
  365. }
  366. /* Copy mbuf data into user buffer */
  367. int16
  368. dqdata(bp,buf,cnt)
  369. struct mbuf *bp;
  370. char *buf;
  371. unsigned cnt;
  372. {
  373.     register unsigned n,tot;
  374.     register struct mbuf *bp1;
  375.  
  376.     if(buf == NULLCHAR)
  377.         return 0;
  378.  
  379.     tot = 0;
  380.     for(bp1 = bp;bp1 != NULLBUF; bp1 = bp1->next){
  381.         n = min(bp1->cnt,cnt);
  382.         memcpy(buf,bp1->data,n);
  383.         cnt -= n;
  384.         buf += n;
  385.         tot += n;
  386.     }
  387.     free_p(bp);
  388.     return tot;
  389. }
  390. /* Pull a 32-bit integer in host order from buffer in network byte order */
  391. int32
  392. pull32(bpp)
  393. struct mbuf *